
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/irq.h>
//#include <asm/arch/regs-gpio.h>
//#include <mach/regs-gpio.h>
//#include <asm/hardware.h>
//#include <mach/hardware.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/rpmsg.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/ioctl.h>

#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 3, 0)
        #include <asm/switch_to.h>
#else
        #include <asm/system.h>
#endif


#define DEVICE_NAME    "rp"    /* 设备名称 */        
static int rp_Major = 0;            /* 主设备号 */

#define MSG		"hello xiao huang! A7->M4"
#define MSG_LIMIT	10
#define RPMSG_DEV_MAX	(MINORMASK + 1)
int n = 0;
char g_buff[1024] = {0};


char message_send[1024] = {"0"}; //a7 ->m4
char message_receive[1024] = {"0"};

struct instance_data 
{
	int rx_count;
};
int flag = 0;
int rflag =0;

 struct rpmsg_device *g_rpdev;

static int rp_cb(struct rpmsg_device *rpdev, void *data, int len,void *priv, u32 src)
{
	//printk( "start   read  data:\n");
	int ret;
	struct instance_data *idata = dev_get_drvdata(&rpdev->dev);
	
	
	printk("rp received_rpmsg: %s %d \n", data, ++idata->rx_count);//打印m4发送过来的数据
	//printk(KERN_DEBUG "received_rpmsg: %s %d \n", data, ++idata->rx_count);//打印m4发送过来的数据
	//memset(message_receive,0,sizeof(message_receive));
    //strcpy(message_receive,data);

	rflag =1;

	return 0;
}

static int rp_probe(struct rpmsg_device *rpdev)
{
	int ret;
	struct instance_data *idata;

	idata = devm_kzalloc(&rpdev->dev, sizeof(*idata), GFP_KERNEL);
	if (!idata)
		return -ENOMEM;

	dev_set_drvdata(&rpdev->dev, idata);


	
	g_rpdev = rpdev; 
	
	/* send a message to our remote processor */
	/*7.15 add*/
	char test[501] = {0};
	memset(test,'1',10);
	ret = rpmsg_send(rpdev->ept, test, strlen(test));
	if (ret) {
		dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret);
		return ret;
	}
	else
		//printk(KERN_DEBUG "send_rpmsg: %s \n", MSG);
		//printk("start:  \n");

	return 0;
}

static void rp_remove(struct rpmsg_device *rpdev)
{
	dev_info(&rpdev->dev, "rpmsg sample client driver is removed\n");
}


static struct rpmsg_device_id rpmsg_driver_sample_id_table[] = {
	{ .name	= "rpmsg-client-sample" },
	{ },
};
MODULE_DEVICE_TABLE(rpmsg, rpmsg_driver_sample_id_table);

static struct rpmsg_driver rpmsg_sample_client =
 {
	.drv.name	= KBUILD_MODNAME,
	.id_table	= rpmsg_driver_sample_id_table,
	.probe		= rp_probe,
	.callback	= rp_cb,
	.remove		= rp_remove,
};


//==============================================

 static  ssize_t  rp_write(struct file *file, const char * buf, size_t count, loff_t *ppos)
 {
	//   copy_from_user(g_buff,buf,count);
	memset(message_send,0,sizeof(message_send));
     copy_from_user(message_send,buf,count);
	if(g_rpdev == NULL)
	{
		printk("g_rpdev  is   NULL");
	}
	else
	{
		printk("g_rpdev  is  not  NULL");
		int ret = rpmsg_send(g_rpdev->ept, message_send, strlen(message_send));//a7给m4发送数据
		if (ret)
			dev_err(&g_rpdev->dev, "rpmsg_send failed: %d\n", ret);
		else
			printk( "send data=%s\n",message_send);
	}
	
	//	flag = 0;
    return count;
 }


static int rp_open(struct inode *inode, struct file *file)
{
//    MOD_INC_USE_COUNT;
    printk("rp Driver Open Called!\n");
	//rpmsg_sample_probe(rpdev);
	
    return 0;
}

ssize_t rp_read(struct file *file, char * buffer, size_t count, loff_t *ppos)
{
	//strcpy(message_receive,buffer);
	if(rflag == 1)
	{
		copy_to_user(buffer,message_receive,count);
		rflag = 0;
	}
	
	//printk(KERN_EMERG "g_buff=[%s]copy to user.%d\n",message_receive,count);
	return count;
}

static int rp_release(struct inode *inode, struct file *file)
{
//    MOD_DEC_USE_COUNT;
    printk("rp Release Called!\n");
    return 0;
}

static long rp_ioctl( struct file *file, unsigned int cmd, unsigned long arg)
{

printk("rp into ioctll\n");
     return -EINVAL;
}

static struct file_operations rp_fops =
{
    .owner  =   THIS_MODULE,
	.open = rp_open,
    .release =  rp_release,
    .unlocked_ioctl  = rp_ioctl,
	.write = rp_write,
    .read = rp_read,
};

static struct class *rp_class;

static int __init RP_init(void)
{

    printk("RP DRIVER MODULE INIT\n");

    rp_Major = register_chrdev(0, DEVICE_NAME, &rp_fops);
    if (rp_Major < 0)
    {
        printk(DEVICE_NAME " can't register major number\n");
        return rp_Major;
    }
    printk("register RP Driver OK! Major = %d\n", rp_Major);

     rp_class = class_create(THIS_MODULE, DEVICE_NAME);
     if(IS_ERR(rp_class))
     {
         printk("Err: failed in RP class. \n");
         return -1;
     }

   int  ret = register_rpmsg_driver(&rpmsg_sample_client);
	if (ret < 0) {
		pr_err("rpmsgchr: failed to register rpmsg driver\n");
		class_destroy(rp_class);
		unregister_chrdev_region(rp_Major, RPMSG_DEV_MAX);
	}

    device_create(rp_class, NULL, MKDEV(rp_Major, 0), NULL, DEVICE_NAME);

    printk(DEVICE_NAME " initialized\n");
	
    return 0;
}

static void __exit RP_exit(void)
{
    printk("RP DRIVER MODULE EXIT\n");
    unregister_chrdev(rp_Major, DEVICE_NAME);
    device_destroy(rp_class, MKDEV(rp_Major, 0));
    class_destroy(rp_class);
    unregister_rpmsg_driver(&rpmsg_sample_client);
}
//module_rpmsg_driver(rpmsg_sample_client);
module_init(RP_init);
module_exit(RP_exit);

MODULE_AUTHOR("  ");        
MODULE_DESCRIPTION("XXXX ");    
MODULE_LICENSE("GPL");
